package tagcloud;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.List;
import tagcloud.component.Article;
import tagcloud.component.ValueVector;
import tagcloud.component.Word;

/**
 *
 * @author thong
 */
public class Histogram {

    Word[] wordWithValue;

    public Histogram(Article[] articles, int threshold) {

        int numberOfArticles = articles.length;

        //get all words
        List<String> words = new LinkedList<>();
        for (Article a : articles) {
            for (Word w : a.words) {
                if (!words.contains(w.word) && w.frequency > threshold) {
                    words.add(w.word);
                }
            }
        }
        //construct important vectors
        ValueVector[] valueVectors = new ValueVector[words.size()];
        for (int i = 0; i < words.size(); i++) {
            String word = words.get(i);
            valueVectors[i] = new ValueVector(word, numberOfArticles);
            for (int j = 0; j < numberOfArticles; j++) {
                valueVectors[i].setValue(j, articles[j].getWordFrequency(word));
            }
        }

        //take out word and sort
        wordWithValue = new Word[valueVectors.length];
        for (int i = 0; i < valueVectors.length; i++) {
            Word w = new Word(valueVectors[i].word, valueVectors[i].getWeight());
            wordWithValue[i] = w;
        }
        for (int i = 0; i < wordWithValue.length - 1; i++) {
            for (int j = i + 1; j < wordWithValue.length; j++) {
                if (wordWithValue[i].frequency < wordWithValue[j].frequency) {
                    //swap position
                    Word tmp = wordWithValue[i];
                    wordWithValue[i] = wordWithValue[j];
                    wordWithValue[j] = tmp;
                }
            }
        }

    }

    public List<Word> getWordWithValue() {
        List<Word> result = new LinkedList<>();
        for (int i = 0; i < wordWithValue.length; i++) {
            result.add(wordWithValue[i]);
        }
        return result;
    }

    final int V_GAP = 50;
    final int H_GAP = 50;
    final int MAX_HEIGHT = 300;
    final int COLUMN_GAP = 10;
    final int COLUMN_WIDTH = 30;
    final int TEXT_XPOS = 0;
    final int TEXT_YPOS = 0;

    public BufferedImage getImage() {
        int numberOfColumn = wordWithValue.length;
        double maxValue = wordWithValue[0].frequency;

        BufferedImage bufferedImage = new BufferedImage(2 * H_GAP + numberOfColumn * (COLUMN_GAP + COLUMN_WIDTH), 2 * V_GAP + MAX_HEIGHT, BufferedImage.TYPE_INT_ARGB);
        //draw
        Graphics g = bufferedImage.getGraphics();
        Color backcolor = new Color(0.5f, 0.5f, 0.5f, 0.05f);
        g.setColor(backcolor);
        g.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());

        //draw axis
        g.setColor(Color.BLACK);
        g.drawLine(V_GAP, H_GAP, V_GAP, H_GAP + MAX_HEIGHT);
        g.drawLine(V_GAP, H_GAP + MAX_HEIGHT, V_GAP + numberOfColumn * (COLUMN_GAP + COLUMN_WIDTH), H_GAP + MAX_HEIGHT);

        //draw horizontal lines
        int space = 0;
        while (space < maxValue) {
            space += 10;
            int value = (int) (space * MAX_HEIGHT / maxValue);
            if (value < MAX_HEIGHT) {
                g.drawLine(V_GAP, H_GAP + MAX_HEIGHT - value, V_GAP + numberOfColumn * (COLUMN_GAP + COLUMN_WIDTH), H_GAP + MAX_HEIGHT - value);
                g.drawString(String.valueOf(space), V_GAP - 25, H_GAP + 5 + MAX_HEIGHT - (int) (space * MAX_HEIGHT / maxValue));
            }
        }

        //draw columns
        Font f = new Font("Tahoma", Font.BOLD, 20);
        g.setFont(f);
        FontMetrics metrics = g.getFontMetrics();
        int text_hgap = (COLUMN_WIDTH + metrics.getHeight()) / 2;
        int text_vgap = 5;
        Color[] colors = produceColorRange(numberOfColumn);
        for (int i = 0; i < numberOfColumn; i++) {
            int columnHeight = (int) (wordWithValue[i].frequency * MAX_HEIGHT / maxValue);
            Point tl = new Point(V_GAP + COLUMN_GAP + i * (COLUMN_WIDTH + COLUMN_GAP), V_GAP + MAX_HEIGHT - columnHeight);
            g.setColor(colors[i]);
            g.fillRect(tl.x, tl.y, COLUMN_WIDTH, columnHeight);
            g.setColor(Color.WHITE);
            drawRotate((Graphics2D) g, tl.x + text_hgap, tl.y + columnHeight - text_vgap, -90, wordWithValue[i].word);
        }
        return bufferedImage;
    }

    private Color[] produceColorRange(int steps) {
        float value = 0.0f; //Starting with full brightness
        Color[] colors = new Color[steps];
        for (int ctr = 0; ctr < steps; ctr++) {
            value = value + (1.0f / steps); //tend to darkness
            int rgb = Color.HSBtoRGB(value, 1.0f, 0.8f); //create a darker color
            //Hue is Blue, not noticeable
            //because Saturation is 0
            Color color = new Color(rgb);
            colors[ctr] = color;
        }
        return colors;
    }

    private static void drawRotate(Graphics2D g2d, double x, double y, int angle, String text) {
        g2d.translate((float) x, (float) y);
        g2d.rotate(Math.toRadians(angle));
        g2d.drawString(text, 0, 0);
        g2d.rotate(-Math.toRadians(angle));
        g2d.translate(-(float) x, -(float) y);
    }
}
